﻿using xn;
using System;

namespace KinectAPI
{
    /// <summary>
    /// Represents the class wich creates the node hand and
    /// tracks it
    /// </summary>
    public class HandTracker : KinectAPIContext
    {

        #region Fields

        /// <summary>
        /// the general OpenNI creator gesture
        /// </summary>
        private GestureGenerator _gestureGenerator;

        /// <summary>
        /// the hands OpenNI creator gesture 
        /// </summary>
        private HandsGenerator _handsGenerator;

        #endregion

        #region Events

        /// <summary>
        /// Hands event handler 
        /// </summary>
        /// <param name="sender">The object firing the event.</param>
        /// <param name="e">Gesture coordinates.</param>
        public delegate void HandPositionHandler(object sender, PositionEventArgs e);

        /// <summary>
        /// Hands event
        /// </summary>
        public event HandPositionHandler HandPosition;

        public delegate void FrameHandler(object sender, PositionEventArgs e);
        public event FrameHandler Frame;


        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new instance of NuiSensor with the default configuration file.
        /// </summary>
        public HandTracker()
            : this(XML_CONFIGURATION)
        {
        }

        /// <summary>
        /// Creates a new instance of NuiSensor with the specified configuration file.
        /// </summary>
        /// <param name="configuration">Configuration file path.</param>
        public HandTracker(string configuration)
        {
            _gestureGenerator = new GestureGenerator(_context);
            _gestureGenerator.AddGesture("Wave");
            _gestureGenerator.GestureRecognized += new GestureGenerator.GestureRecognizedHandler(GestureGenerator_GestureRecognized);

            _handsGenerator = new HandsGenerator(_context);
            _handsGenerator.HandUpdate += new HandsGenerator.HandUpdateHandler(HandsGenerator_HandUpdate);

            _gestureGenerator.StartGenerating();
            _handsGenerator.StartGenerating();
        }

        #endregion

        #region Event Handler

        /// <summary>
        /// Starts hands gestures tracking
        /// </summary>
        /// <param name="node">The hand node</param>
        /// <param name="strGesture">The gesture to recognize</param>
        /// <param name="idPosition">The point position represented by an id</param>
        /// <param name="endPosition">The final position position</param>
        void GestureGenerator_GestureRecognized(ProductionNode node, string strGesture, ref Point3D idPosition, ref Point3D endPosition)
        {
            _handsGenerator.StartTracking(ref endPosition); //start the hand tracking
            //_gestureGenerator.RemoveGesture(strGesture);
        }

        /// <summary>
        /// Tracks hands gestures from the beginning until the end of the execution
        /// </summary>
        /// <param name="node">The updated hand node</param>
        /// <param name="id"></param>
        /// <param name="position">The hand position</param>
        /// <param name="fTime"></param>
        void HandsGenerator_HandUpdate(ProductionNode node, uint id, ref Point3D position, float fTime)
        {
            Point3D projectivePosition = _depthGenerator.ConvertRealWorldToProjective(position);
            HandPosition(this, new PositionEventArgs(projectivePosition.X, projectivePosition.Y, projectivePosition.Z));
            Frame(this, new PositionEventArgs(projectivePosition.X, projectivePosition.Y, projectivePosition.Z));
        }

        #endregion

    }
}
